Python递归算法小结

一、递归的定义

程序调用自身的编程技巧称为递归( recursion)。

递归函数就是直接或间接调用自身的函数。

#直接调用自己:
def func():
    print('from func')
    func()

func()


#间接调用自己
def foo():
    print('from foo')
    bar()

def bar():
    print('from bar')
    foo()

foo()

二、递归经典例子

1、斐波那契数列

描述:斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368........这个数列从第3项开始,每一项都等于前两项之和。

class Solution:
    # 递归
    def Fibonacci(self, n):        
        if n == 1:
            return 1
        return self.Fibonacci(n-1)+self.Fibonacci(n-2)
    
    #非递归
    def Fibonacci2(self, n):
        a, b = 0, 1
        for i in range(n):
            a, b = b, a+b
        return b

f = Solution()
print(f.Fibonacci(10))
print(f.Fibonacci2(10))

2、汉诺塔

描述:汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。 

def move(n,a,b,c):
    if n == 1:
        print(a,'-->',c)

    else:
        move(n-1,a,c,b)
        move(1,a,b,c)
        move(n-1,b,a,c)

move(3,'a','b','c')

输出结果:

a --> c
a --> b
c --> b
a --> c
b --> a
b --> c
a --> c

3、八皇后

描述:八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。

def conflict(state , nextX):
    nextY = len(state)
    for i in range(nextY):
        if abs(state[i] - nextX) in (0 , nextY - i ):
            return True
    return False

def queens(num = 8 , state = ()):
    for pos in range(num):
        if not conflict(state, pos):
            if len(state) == num - 1:
                yield (pos,)
            else:
                for result in queens(num , state + (pos,)):
                    yield (pos, ) + result

if __name__=='__main__':    
    print(len(list(queens(8))))
    

分享一种效率更高的方法

class Queen:
    def __init__(self, q=8):
        self.q = q
        self.col = [1] * q  # 矩阵列的列表,存储皇后所在列,若该列没有皇后,则相应置为1,反之则0
        self.row = [0] * q  # 矩阵行的列表,存放每行皇后所在的列位置,随着程序的执行,在不断的变化中,之间输出结果
        self.pos_diag = [1] * (q*2+1)  # 正对角线,i-j恒定,-7~0~7,并且b(i)+7统一到0~14
        self.nag_diag = [1] * (q*2+1)  # 负对角线,i+j恒定,0~14
        self.count = 0

    def getcount(self):
        return self.count

    def do_queen(self, i):
        for j in range(0, self.q):
            if self.col[j] == 1 and self.pos_diag[i-j+self.q-1] == 1 and self.nag_diag[i+j] == 1:
                #若该行,正对角线,负对角线上都没有皇后,则放入i皇后
                self.row[i] = j
                self.col[j] = 0                      #调整各个列表状态
                self.pos_diag[i-j+self.q-1] = 0
                self.nag_diag[i+j] = 0
                if i < self.q-1:
                    self.do_queen(i+1)               #可递增或递减
                else:
                    # print(self.row)
                    self.count += 1
                self.col[j] = 1                      #恢复各个列表状态为之前的
                self.pos_diag[i-j+self.q-1] = 1
                self.nag_diag[i+j] = 1

if __name__ == '__main__':    
    f = Queen(8)
    f.do_queen(0)
    print(f.getcount())
    
   

 

  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值